package layers.agents;

import layers.ants.IntentionAnt;
import layers.physical.Crossroad;
import layers.physical.Path;
import layers.physical.Road;
import layers.physical.Truck;

import commands.EnterCrossroadCommand;
import commands.LeaveCrossroadCommand;
import commands.MoveForwardCommand;

import events.truckEvents.TruckEndedDrivingToPackageEvent;
import events.truckEvents.TruckStartedDrivingToPackageEvent;
import framework.events.EventBroker;

public class TruckAgentStateExecutingIntention extends TruckAgentState {

	private Path intention;

	public TruckAgentStateExecutingIntention(TruckAgent agent, Path intention) {
		super(agent);
		this.intention = intention;
		EventBroker.getEventBroker().notifyAll(new TruckStartedDrivingToPackageEvent(this.getAgent().getTruck()));
	}

	protected void confirmIntention(Path path){
		//NO-OP
	}

	protected void rejectIntention(Path path){
		this.getAgent().setState(new TruckAgentStateCreatingIntention(getAgent()));
		EventBroker.getEventBroker().notifyAll(new TruckEndedDrivingToPackageEvent(this.getAgent().getTruck()));
		clearAgent();
	}

	@Override
	protected void processTick() {
		this.followRoute();	
		//TODO Mss niet elke tick een intention ant uitsturen?
		if(this.getAgent() != null){
			new IntentionAnt(getAgent().getLastCr(), getAgent(), getRemainingPath());
		}
	}

	private Path getRemainingPath() {
		//		return intention.getTrimmedPath(false);//!isOnConnector);
		Crossroad cr = this.getAgent().getLastCr();
		return intention.getPathStartingFrom(cr);
	}

	protected void followRoute() {
		Truck truck = this.getAgent().getTruck();
		if (truck.allCommandsProcessed()) {
			if(!intention.isAtLast(truck) || !truck.isOnConnector()){
				if (truck.isOnConnector()) {
					Crossroad cr1 = truck.getConnectorPosition().getConnector();
					Crossroad cr2 = intention.getCrossroadNextTo(cr1);
					Road road = cr1.getConnectionTo(cr2);
					truck.addCommand(new LeaveCrossroadCommand(truck, road), this.getAgent());
					this.getAgent().setLastCr(cr1);
				} else if (truck.isOnConnection() && truck.getConnectionPosition().getConnection().isAtEnd(truck)) {
					truck.addCommand(new EnterCrossroadCommand(truck), this.getAgent());
				} else if (truck.isOnConnection() && !truck.getConnectionPosition().getConnection().isAtEnd(truck)) {
					truck.addCommand(new MoveForwardCommand(truck), this.getAgent());
				}
			}else{
				pickUpPackage();
			}
		}
	}

	private void pickUpPackage() {
		Crossroad cr = this.getAgent().getTruck().getConnectorPosition().getConnector();
		PackageAgent pa = cr.getPackageAgent();
		if(pa != null){
			((TruckAgent) this.getAgent()).addPackage(cr.getPackageAgent());
			cr.getPackageAgent().notifyOfPickup();
			this.getAgent().setState(new TruckAgentStateDrivingToDestination(getAgent(), pa.getDeliveryPath()));
			EventBroker.getEventBroker().notifyAll(new TruckEndedDrivingToPackageEvent(this.getAgent().getTruck()));
			this.clearAgent();
		}
	}
}
